package com.relytosoft.mizar.media.analyze.services.service.system.impl;


import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.relytosoft.dubhe.common.core.base.page.PageQuery;
import com.relytosoft.dubhe.common.core.utils.BeanCopyUtils;
import com.relytosoft.dubhe.common.redis.utils.RedisUtil;
import com.relytosoft.mizar.media.analyze.api.entity.system.AyVehicleGroup;
import com.relytosoft.mizar.media.analyze.api.entity.system.AyVehicleInfo;
import com.relytosoft.mizar.media.analyze.api.pojo.vo.AyVehicleInfoVo;
import com.relytosoft.mizar.media.analyze.api.pojo.vo.VehicleInfoImportVo;
import com.relytosoft.mizar.media.analyze.services.listener.VehicleInfoExcelListener;
import com.relytosoft.mizar.media.analyze.services.mapper.system.AyVehicleInfoMapper;
import com.relytosoft.mizar.media.analyze.services.service.system.AyVehicleGroupService;
import com.relytosoft.mizar.media.analyze.services.service.system.AyVehicleInfoService;
import com.relytosoft.mizar.media.common.constant.AyCacheConstants;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author lj
 * @date 2022/5/12 11:07
 */
@Service
public class AyVehicleInfoServiceImpl extends ServiceImpl<AyVehicleInfoMapper, AyVehicleInfo> implements AyVehicleInfoService {
    @Resource
    private AyVehicleGroupService ayVehicleGroupService;

    @Override
    public IPage<AyVehicleInfo> selectAyVehicleInfoPageList(PageQuery pageQuery, AyVehicleInfo ayVehicleInfo) {
        if (StrUtil.isBlank(pageQuery.getOrderByColumn())) {
            pageQuery.setOrderByColumn("id");
            pageQuery.setIsAsc("desc");
        }
        return baseMapper.selectPageInfoList(pageQuery.build(), ayVehicleInfo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean addAyVehicleInfo(AyVehicleInfo ayVehicleInfo) {
        //添加到本地数据库
        ayVehicleInfo.setStatus(1);
        boolean save = this.save(ayVehicleInfo);
        if (save) {
            //添加关联信息
            List<Integer> groupIds = ayVehicleInfo.getGroupIds();
            List<AyVehicleGroup> ayVehicleGroupList = new ArrayList<>();
            groupIds.forEach(groupId -> {
                AyVehicleGroup ayVehicleGroup = new AyVehicleGroup();
                ayVehicleGroup.setGroupId(groupId);
                ayVehicleGroup.setVehicleId(ayVehicleInfo.getId());
                ayVehicleGroupList.add(ayVehicleGroup);
                RedisUtil.sSet(AyCacheConstants.VEHICLE_GROUP + groupId, ayVehicleInfo.getId());
            });
            save = ayVehicleGroupService.saveBatch(ayVehicleGroupList);
        }

        return save;
    }


    /**
     * 删除
     *
     * @param list 需要删除的车辆ID集合
     */
    @Override
    public boolean updateAyVehicleInfoStatus(List<Integer> list) {
        LambdaQueryWrapper<AyVehicleInfo> wrapper = new QueryWrapper<AyVehicleInfo>().lambda();
        wrapper.eq(AyVehicleInfo::getStatus, 1)
                .in(list.size() > 0, AyVehicleInfo::getId, list);
        //删除车信息
        boolean flag = this.update(new AyVehicleInfo(0), wrapper);

        //删除该车关联信息
        if (flag) {

            LambdaQueryWrapper<AyVehicleGroup> ayVehicleInfoWrapper = new QueryWrapper<AyVehicleGroup>().lambda();
            ayVehicleInfoWrapper.in(list.size() > 0, AyVehicleGroup::getVehicleId, list);

            //查询车辆关联的组信息
            List<Integer> groupIds = ayVehicleGroupService.list(ayVehicleInfoWrapper).
                    stream()
                    //收集group变为集合
                    .map(AyVehicleGroup::getGroupId)
                    //收集groupId
                    .collect(Collectors.toList());

            flag = ayVehicleGroupService.remove(ayVehicleInfoWrapper);

            //循环删除组信息
            groupIds.forEach(groupId -> {
                RedisUtil.setRemove(AyCacheConstants.VEHICLE_GROUP + groupId, list.toArray());
                System.out.println("删除+" + groupId);
            });
        }
        return flag;
    }

    @Override
    public AyVehicleInfoVo selectByVehicleId(Integer vehicleId) {
        AyVehicleInfo ayVehicleInfo = this.getById(vehicleId);
        ayVehicleInfo.setGroupIds(ayVehicleGroupService.selectByVehicleId(ayVehicleInfo.getId()));
        return BeanCopyUtils.copy(ayVehicleInfo, AyVehicleInfoVo.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateAyVehicleInfo(AyVehicleInfo ayVehicleInfo) {
        //修改基础数据
        boolean flag = this.updateById(ayVehicleInfo);
        //修改关联表数据
        //获取新的关联的库数据
        List<Integer> groupIds = ayVehicleInfo.getGroupIds();
        //获取以前关联的库的数据
        List<Integer> oldGroups = ayVehicleGroupService.selectByVehicleId(ayVehicleInfo.getId());
        //去除相同的剩下的就是旧的需要删除的数据
        oldGroups.removeAll(groupIds);
        if (flag && oldGroups.size() > 0) {
            //删除旧的关联信息
            flag = ayVehicleGroupService.selectByVehicleIdAndGroupIds(ayVehicleInfo.getId(), oldGroups);
            //删除缓存
            oldGroups.forEach(groupId -> {
                RedisUtil.setRemove(AyCacheConstants.VEHICLE_GROUP + groupId, ayVehicleInfo.getId());
            });
        }
        if (flag && groupIds.size() > 0) {
            //保存或不变更改的关联的信息
            //根据车ID和组ID判断该数据是否存在
            List<AyVehicleGroup> ayVehicleGroupList = new ArrayList<>();
            groupIds.forEach(groupId -> {
                AyVehicleGroup ayVehicleGroup = ayVehicleGroupService.selectVehicleIdAndGroupId(ayVehicleInfo.getId(), groupId);
                if (ayVehicleGroup == null) {
                    AyVehicleGroup group = new AyVehicleGroup();
                    group.setGroupId(groupId);
                    group.setVehicleId(ayVehicleInfo.getId());
                    ayVehicleGroupList.add(group);
                    //添加缓存
                    RedisUtil.sSet(AyCacheConstants.VEHICLE_GROUP + groupId, ayVehicleInfo.getId());
                }
            });
            if (ayVehicleGroupList.size() > 0) {
                flag = ayVehicleGroupService.saveBatch(ayVehicleGroupList);
            }
        }
        return flag;
    }

    @Override
    public void importTemplate(HttpServletResponse response) {
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("模板.xlsx", "utf-8");
            response.setHeader("Content-disposition", "attachment; filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
            VehicleInfoImportVo vehicleInfoImportVo = new VehicleInfoImportVo();
            vehicleInfoImportVo.setVehicleNumber("例如：京A·88888");
            vehicleInfoImportVo.setVehicleType("选择其中一种：小型车 大型车 摩托车 其他车");
            vehicleInfoImportVo.setRemark("备注");
            ArrayList<VehicleInfoImportVo> arrayList = new ArrayList<>();
            arrayList.add(vehicleInfoImportVo);
            EasyExcel.write(response.getOutputStream(), VehicleInfoImportVo.class).sheet("模板").doWrite(arrayList);
            response.getOutputStream().close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public void saveVehicleInfo(MultipartFile file, AyVehicleInfoService ayVehicleInfoService, List<Integer> ids) {
        try {
            InputStream inputStream = file.getInputStream();
            //new VehicleInfoExcelListener，表明这个组件没有交给spring ioc容器来管理，没有给这个组件注册到spring ioc容器里面
            EasyExcel.read(inputStream, VehicleInfoImportVo.class, new VehicleInfoExcelListener(ayVehicleInfoService, ids, ayVehicleGroupService)).sheet().doRead();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
